package components;


import java.util.List;

import com.uqbar.vainilla.DeltaState;
import com.uqbar.vainilla.GameComponent;
import com.uqbar.vainilla.colissions.CollisionDetector;
import components.asteroids.Asteroid;
import components.scenes.CollisionablesScene;
import components.ship.Ship;
import components.weapon.Proyectile;

public abstract class CollisionableComponent<SceneType extends CollisionablesScene> 
	extends GameComponent<SceneType> {
	
	private CollisionDetector detector;
	private int diameter;
	private int height;
	private boolean canMove;
	
	public int getDiameter() {
		return diameter;
	}

	public void setDiameter(int diameter) {
		this.diameter = diameter;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	
	public CollisionableComponent(int aDiameter, int aHeight, double x, double y){
		this.canMove = true;
		this.diameter = aDiameter;
		this.height = aHeight;
		this.setX(x);
		this.setY(y);
		this.setDetector(CollisionDetector.INSTANCE);
	}
	

	public abstract boolean isSolid();

	public CollisionDetector getDetector() {
		return detector;
	}

	public void setDetector(CollisionDetector detector) {
		this.detector = detector;
	}
	
	public void updateCoords(double diffX, double diffY) {
		this.getSceneTableComps().move(this, this.getX(), this.getY(), this.getX() + diffX, this.getY() + diffY);
		this.move(diffX, diffY);
	}
	public void relocate(double x, double y){
		this.getSceneTableComps().move(this, this.getX(), this.getY(), x, y);
		this.setX(x);
		this.setY(y);
	}
	public ComponentsHashTable getSceneTableComps() {
		return this.getScene().getComponentsTable();
	}
	
	public boolean collide(double nx, double ny){
		List<CollisionableComponent> comps = this.getSceneTableComps().getComponentsNearSectorExcluding(this, nx, ny, this.diameter, this.height);
		for (CollisionableComponent gc : comps){
				if (this.getDetector().collidesRectAgainstRect(nx, ny,this.diameter, this.height,
						gc.getX(), gc.getY(), (int) gc.getAppearance().getWidth(), (int)gc.getAppearance().getHeight())){
					this.defineCollide(gc);
					if (gc.isSolid()){
						this.onCollisionWithSolid(gc);
						return true;
					}
				}
			}
		return false;
	}

	protected abstract void onCollisionWithSolid(CollisionableComponent gc);
		

	protected abstract void defineCollide(CollisionableComponent gc);


	public void update(DeltaState deltaState) {
		super.update(deltaState);
		if (deltaState.getDelta() < 0.1){
			this.effectiveUpdate(deltaState);
		}
	}
	
	protected void generciMove(DeltaState delta, double speed, double xdir, double ydir){
		double intensity = delta.getDelta() * speed;
		double nx, ny;
		nx = this.getX() + intensity*xdir;
		ny = this.getY() + intensity*ydir;
		
		this.collide(nx, ny);
		
		if (this.canMove()){
			this.updateCoords(intensity*xdir, intensity*ydir);
		}
		
	}
	

	protected abstract void effectiveUpdate(DeltaState deltaState);
		
	public void destroyComponent(){
		this.getSceneTableComps().remove(this, this.getX(), this.getY());
		this.destroy();
	}

	public void collideWithShip(Ship ship) {
		
	}
	public void collideWithProyectile(Proyectile proyectile) {
		
	}

	public void collideWithAsteroid(Asteroid asteroid) {
		
	}

	public boolean canMove() {
		return canMove;
	}

	public void setCanMove(boolean canMove) {
		this.canMove = canMove;
	}

	
}
